package com.tbit.uqbike.client.controller;

import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.response.AlipayTradeCreateResponse;
import com.tbit.uqbike.client.aop.charge.ChargeReturnBikeLimit;
import com.tbit.uqbike.client.aop.charge.RechargeTypeParam;
import com.tbit.uqbike.client.aop.charge.TokenParam;
import com.tbit.uqbike.client.constant.DepositStateConstant;
import com.tbit.uqbike.client.constant.RechargeConstant;
import com.tbit.uqbike.client.constant.RedisConstant;
import com.tbit.uqbike.client.constant.ResponseCode;
import com.tbit.uqbike.client.constant.annotation.PreventDuplication;
import com.tbit.uqbike.client.exception.BaseException;
import com.tbit.uqbike.client.pojo.Recharge;
import com.tbit.uqbike.client.pojo.User;
import com.tbit.uqbike.client.pojo.ZfbPayConfig;
import com.tbit.uqbike.client.remote.zfb.config.AlipayConfig;
import com.tbit.uqbike.client.service.*;
import com.tbit.uqbike.client.util.Assert;
import com.tbit.uqbike.client.util.DateTimeUtil;
import com.tbit.uqbike.client.util.OutputUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * 支付宝支付
 *
 * @author Leon
 * 2019年10月31日 上午10:29:48
 */
@Controller
@RequestMapping("/zhifubaoPay")
@Slf4j
public class ZhifubaoPayController {
    @Autowired
    private ZhifubaoPayService zhifubaoPayService;
    @Autowired
    private TokenService tokenService;
    @Autowired
    private RechargeService rechargeService;
    @Autowired
    private UserService userService;
    @Autowired
    private ZfbPayConfigService zfbPayConfigService;
    @Autowired
    private RedisService redisService;
    @Autowired
    private WeixinPayService weixinPayService;
    @Autowired
    private MQProducer mqProducer;

    /**
     * 创建APP支付订单
     *
     * @param token        令牌
     * @param adAccountId  区域id
     * @param money        金额
     * @param remark       备注
     * @param deposit      是否押金
     * @param rechargeType 充值类型
     * @param dispatchType 调度类型
     * @param session      会话
     * @param response     响应
     * @ignoreParams request
     */
    @RequestMapping("/createOrder")
    @PreventDuplication(expireSeconds = 5)
    @ChargeReturnBikeLimit
    public void createOrder(@TokenParam String token, Integer adAccountId, Double money, String remark, Boolean deposit, @RequestParam(defaultValue = "0") @RechargeTypeParam Integer rechargeType, Integer dispatchType, HttpSession session, HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> map = new HashMap<String, Object>();
        try {

            if (deposit == null) {
                deposit = false;
            }
            User user = tokenService.getUser(token);
            if (deposit) {
                Assert.notNull(adAccountId, "-10001", "区域id不能为空");
            }
            if (!deposit) {
                /* 校验 */
                Assert.notNull(money, "-70001", "充值金额不能为空");
                if (adAccountId != null) {
                    redisService.add(user.getUserId() + ".agentId", String.valueOf(adAccountId), 30);
                }
            }

            /**充值结束订单需要校验下用户点击还车检验到创建订单时长，超出1分钟不许还车*/
            if (rechargeType.equals(RechargeConstant.recharge_returnBike)) {
                String no = redisService.get(RedisConstant.USER_FINISH_PAY + user.getUserId());
                if (no == null) {
                    throw new BaseException("-20018", "订单超时，请重试");
                }
            }

            /**存储调度类型还车*/
            if (dispatchType != null) {
                redisService.add(RedisConstant.REDIS_ACCOUNT_USER_DISPATCH + user.getUserId(), String.valueOf(dispatchType), 90);
            }
            String result = zhifubaoPayService.getOrder(user.getAccountId(), user.getUserId(), money, remark, deposit, adAccountId, rechargeType);
            //log.error("结果="+result);
            map.put(ResponseCode.RET, ResponseCode.SUCC);
            map.put(ResponseCode.DATA, result);

        } catch (BaseException e) {
            ResponseCode.printException(map, e, request);
        }

        OutputUtil.renderText(request, response, map);
    }

    /* 支付宝异步通知 */
    @SuppressWarnings("rawtypes")
    @RequestMapping("/alipayNotify")
    public void alipayNotify(
            HttpServletRequest request, HttpServletResponse response, HttpSession session) throws UnsupportedEncodingException {
        // 获取支付宝POST过来反馈信息
        Map<String, String> params = new HashMap<String, String>();
        Map requestParams = request.getParameterMap();
        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            params.put(name, valueStr);
        }
        String out_trade_no = "";
        String notifyType = params.get("notify_type");
        if ("fund_auth_freeze".equalsIgnoreCase(notifyType)) {
            out_trade_no = new String(request.getParameter("out_order_no").getBytes("ISO-8859-1"), "UTF-8");
        } else if ("fund_auth_unfreeze".equalsIgnoreCase(notifyType)) {
            out_trade_no = new String(request.getParameter("out_order_no").getBytes("ISO-8859-1"), "UTF-8");
        } else {
            out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8");
        }
        log.info("支付宝回调 " + params.toString());
        // 商户订单号

        /** 查询订单 */
        Recharge recharge = rechargeService.getByOrderNO(out_trade_no);
        if (recharge == null) {
            log.error("订单不存在" + out_trade_no);
            OutputUtil.renderHtml(request, response, "fail");
        }
        /** 查询支付配置 */
        User user = userService.getByUserId(recharge.getUserId());
        if (user == null) {
            log.error("用户不存在");
            OutputUtil.renderHtml(request, response, "fail");
        }
        ZfbPayConfig zfbPayConfig = null;
        if (recharge.getType() == RechargeConstant.RECHARGE_ZFB_APP) {
            zfbPayConfig = zfbPayConfigService.getByAccountId(user.getAccountId(), RechargeConstant.ZFB_PAY_APP);
        } else if (recharge.getType() == RechargeConstant.RECHARGE_ZFB_XCX) {
            zfbPayConfig = zfbPayConfigService.getByAccountId(user.getAccountId(), RechargeConstant.ZFB_PAY_XCX);
        }
        if (zfbPayConfig == null) {
            log.error("支付宝配置不存在");
            OutputUtil.renderHtml(request, response, "fail");
        }

        try {
            if (AlipaySignature.rsaCheckV1(params, zfbPayConfig.getAli_public_key(), AlipayConfig.input_charset, "RSA2")) {// 验证成功

                switch (notifyType) {
                    /*预授权支付回调处理*/
                    case "fund_auth_freeze":
                        String status = new String(request.getParameter("status").getBytes("ISO-8859-1"), "UTF-8");
                        if ("SUCCESS".equalsIgnoreCase(status)) {
                            userService.updateDeposit(user.getUserId(), DepositStateConstant.DEPOSIT_STATE_ZMXY);
                            String gmt_trans = new String(request.getParameter("gmt_trans").getBytes("ISO-8859-1"), "UTF-8");
                            recharge.setPayTime(gmt_trans);
                            String auth_no = new String(request.getParameter("auth_no").getBytes("ISO-8859-1"), "UTF-8");
                            recharge.setRemark(auth_no);
                            recharge.setState(1);
                            rechargeService.editWizffPay(recharge);
                        }
                        break;
                    case "fund_auth_unfreeze":
                        status = new String(request.getParameter("status").getBytes("ISO-8859-1"), "UTF-8");
                        if ("SUCCESS".equalsIgnoreCase(status)) {
                            userService.updateDeposit(user.getUserId(), DepositStateConstant.DEPOSIT_STATE_NOTPAY);
                            recharge.setState(2);
                            rechargeService.editWizffPay(recharge);
                        }
                        break;
                    case "trade_status_sync":
                        // 支付宝交易号
                        String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8");
                        // 交易状态
                        String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"), "UTF-8");
                        // 订单金额
                        Double total_amount = new Double(request.getParameter("total_amount"));

                        log.info("[支付宝]商户订单号:" + out_trade_no + ";支付宝交易号:" + trade_no + ";交易状态:" + trade_status + ",金额:" + total_amount);

                        if (trade_status.equals("TRADE_SUCCESS")) {
                            if (recharge.getState() == 0) {
                                /** 查询金额是否和订单一致 */
                                Double rechargeMondey = recharge.getMoney() / 100;
                                Double zfbMoney = total_amount;
                                if (!rechargeMondey.equals(zfbMoney)) {
                                    log.error("订单金额与支付金额不一致,订单号=" + out_trade_no + ",订单金额=" + rechargeMondey + "元,支付金额=" + zfbMoney + "元");
                                } else {
                                    String dateTime = DateTimeUtil.getNowTime();
                                    if (request.getParameter("gmt_payment") != null) {
                                        dateTime = new String(request.getParameter("gmt_payment").getBytes("ISO-8859-1"), "UTF-8");
                                    }
                                    mqProducer.sendPay(out_trade_no, out_trade_no, trade_no, dateTime, null);
                                }

                            } else {
                                log.error("没有查询到支付订单，订单号=" + out_trade_no);
                            }
                        }
                        break;
                    default:

                        break;

                }


                OutputUtil.renderHtml(request, response, "success");
            } else {
                log.error("验证失败");
                OutputUtil.renderHtml(request, response, "fail");
            }
        } catch (AlipayApiException e) {
            log.error("验证失败", e);
        }
    }


    /**
     * 创建免押会员订单——app
     *
     * @param token       令牌
     * @param memberFeeId 免押会员id
     * @param adAccountId 区域id
     * @param session     会话
     * @param response    响应
     * @ignoreParams request
     */
    @RequestMapping("/createOrder_memberFee")
    @PreventDuplication(expireSeconds = 5)
    public void createOrder_memberFee(String token, Integer memberFeeId, Integer adAccountId, HttpSession session, HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> map = new HashMap<String, Object>();
        try {

            User user = tokenService.getUser(token);
            Assert.notNull(memberFeeId, "-130003", "memberFeeId不能为空");
            Assert.notNull(adAccountId, "-10001", "区域id不能为空");
            /**放入redis*/
            redisService.add(user.getUserId() + ".agentId", String.valueOf(adAccountId), 600);

            String result = zhifubaoPayService.createOrder_memberFee(user, memberFeeId, adAccountId);

            map.put(ResponseCode.RET, ResponseCode.SUCC);
            map.put(ResponseCode.DATA, result);
        } catch (BaseException e) {
            ResponseCode.printException(map, e, request);
        }

        OutputUtil.renderText(request, response, map);
    }


    /**
     * 创建骑行会员订单-app
     *
     * @param token       令牌
     * @param rideCardId  骑行卡id
     * @param adAccountId 区域id
     * @param session     会话
     * @param response    响应
     * @ignoreParams request
     */
    @RequestMapping("/createOrder_rideCard")
    @PreventDuplication(expireSeconds = 5)
    public void createOrder_rideCard(String token, Integer rideCardId, Integer adAccountId, HttpSession session, HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> map = new HashMap<String, Object>();
        try {

            User user = tokenService.getUser(token);
            Assert.notNull(rideCardId, "-120001", "骑行会员卡id不能为空");
            Assert.notNull(adAccountId, "-10001", "区域id不能为空");
            String result = zhifubaoPayService.createOrder_rideCard(user, rideCardId, adAccountId);

            map.put(ResponseCode.RET, ResponseCode.SUCC);
            map.put(ResponseCode.DATA, result);
        } catch (BaseException e) {
            ResponseCode.printException(map, e, request);
        }

        OutputUtil.renderText(request, response, map);
    }


    /**
     * 创建会员卡订单-app
     *
     * @param token       令牌
     * @param vipId       vip会员卡Id
     * @param adAccountId 区域id
     * @param session     会话
     * @param response    响应
     * @ignoreParams request
     */
    @RequestMapping("/createOrder_vip")
    @PreventDuplication(expireSeconds = 5)
    public void createOrder_vip(String token, Integer vipId, Integer adAccountId, HttpSession session, HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> map = new HashMap<String, Object>();
        try {

            User user = tokenService.getUser(token);
            Assert.notNull(vipId, "-150001", "vipId不能为空");
            Assert.notNull(adAccountId, "-10001", "区域id不能为空");
            String result = zhifubaoPayService.createOrder_vip(user, vipId, adAccountId);

            map.put(ResponseCode.RET, ResponseCode.SUCC);
            map.put(ResponseCode.DATA, result);
        } catch (BaseException e) {
            ResponseCode.printException(map, e, request);
        }

        OutputUtil.renderText(request, response, map);
    }


    /**
     * 创建支付宝小程序支付订单
     *
     * @param token        令牌
     * @param code         代码
     * @param adAccountId  区域id
     * @param money        金额
     * @param remark       备注
     * @param deposit      是否押金
     * @param rechargeType 充值类型
     * @param dispatchType 调度类型
     * @param session      会话
     * @param response     响应
     * @ignoreParams request
     */
    @RequestMapping("/createOrder_xcx")
    @PreventDuplication(expireSeconds = 5)
    @ChargeReturnBikeLimit
    public void createOrder_xcx(@TokenParam String token, String code, Integer adAccountId, Double money, String remark, Boolean deposit, @RequestParam(defaultValue = "0") @RechargeTypeParam Integer rechargeType, Integer dispatchType, HttpSession session, HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> map = new HashMap<String, Object>();
        try {

            Assert.notNull(code, "", "");

            if (deposit == null) {
                deposit = false;
            }
            User user = tokenService.getUser(token);
            if (deposit) {
                Assert.notNull(adAccountId, "-10001", "区域id不能为空");
            }
            if (!deposit) {
                /* 校验 */
                Assert.notNull(money, "-70001", "充值金额不能为空");
                if (adAccountId != null) {
                    redisService.add(user.getUserId() + ".agentId", String.valueOf(adAccountId), 600);
                }
            }

            /**充值结束订单需要校验下用户点击还车检验到创建订单时长，超出1分钟不许还车*/
            if (rechargeType.equals(RechargeConstant.recharge_returnBike)) {
                String no = redisService.get(RedisConstant.USER_FINISH_PAY + user.getUserId());
                if (no == null) {
                    throw new BaseException("-20018", "订单超时，请重试");
                }
            }

            /**存储调度类型还车*/
            if (dispatchType != null) {
                redisService.add(RedisConstant.REDIS_ACCOUNT_USER_DISPATCH + user.getUserId(), String.valueOf(dispatchType), 90);
            }
            AlipayTradeCreateResponse alipayTradeCreateResponse = zhifubaoPayService.getOrder_xcx(user.getAccountId(), code, user.getUserId(), money, remark, deposit, adAccountId, rechargeType);

            map.put(ResponseCode.RET, ResponseCode.SUCC);
            map.put(ResponseCode.DATA, alipayTradeCreateResponse);
        } catch (BaseException e) {
            ResponseCode.printException(map, e, request);
        }

        OutputUtil.renderText(request, response, map);
    }


    /**
     * 创建小程序免押会员订单
     *
     * @param token       令牌
     * @param code        代码
     * @param memberFeeId 免押会员id
     * @param adAccountId 区域id
     * @param session     会话
     * @param response    响应
     * @ignoreParams request
     */
    @RequestMapping("/createOrder_memberFee_xcx")
    @PreventDuplication(expireSeconds = 5)
    public void createOrder_memberFee_xcx(String token, String
            code, Integer memberFeeId, Integer adAccountId, HttpSession session, HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> map = new HashMap<String, Object>();
        try {

            User user = tokenService.getUser(token);
            Assert.notNull(memberFeeId, "-130003", "memberFeeId不能为空");
            Assert.notNull(adAccountId, "-10001", "区域id不能为空");
            /**放入redis*/
            redisService.add(user.getUserId() + ".agentId", String.valueOf(adAccountId), 600);

            AlipayTradeCreateResponse alipayTradeCreateResponse = zhifubaoPayService.createOrder_memberFee_xcx(user, code, memberFeeId, adAccountId);

            map.put(ResponseCode.RET, ResponseCode.SUCC);
            map.put(ResponseCode.DATA, alipayTradeCreateResponse);
        } catch (BaseException e) {
            ResponseCode.printException(map, e, request);
        }

        OutputUtil.renderText(request, response, map);
    }


    /**
     * 创建小程序骑行会员订单
     *
     * @param token       令牌
     * @param code        代码
     * @param rideCardId  骑行卡id
     * @param adAccountId 区域id
     * @param session     会话
     * @param response    响应
     * @ignoreParams request
     */
    @RequestMapping("/createOrder_rideCard_xcx")
    @PreventDuplication(expireSeconds = 5)
    public void createOrder_rideCard_cxc(String token, String code, Integer rideCardId, Integer adAccountId, HttpSession session, HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> map = new HashMap<String, Object>();
        try {

            User user = tokenService.getUser(token);
            Assert.notNull(rideCardId, "-120001", "骑行会员卡id不能为空");
            Assert.notNull(adAccountId, "-10001", "区域id不能为空");
            AlipayTradeCreateResponse alipayTradeCreateResponse = zhifubaoPayService.createOrder_rideCard_xcx(user, code, rideCardId, adAccountId);

            map.put(ResponseCode.RET, ResponseCode.SUCC);
            map.put(ResponseCode.DATA, alipayTradeCreateResponse);
        } catch (BaseException e) {
            ResponseCode.printException(map, e, request);
        }

        OutputUtil.renderText(request, response, map);
    }


    /**
     * 创建小程序会员卡订单
     *
     * @param token       令牌
     * @param code        代码
     * @param vipId       会员卡id
     * @param adAccountId 区域id
     * @param session     会话
     * @param response    响应
     * @ignoreParams request
     */
    @RequestMapping("/createOrder_vip_xcx")
    @PreventDuplication(expireSeconds = 5)
    public void createOrder_vip_cxc(String token, String code, Integer vipId, Integer adAccountId, HttpSession session, HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> map = new HashMap<String, Object>();
        try {

            User user = tokenService.getUser(token);
            Assert.notNull(vipId, "-150001", "vipId不能为空");
            Assert.notNull(adAccountId, "-10001", "区域id不能为空");
            AlipayTradeCreateResponse alipayTradeCreateResponse = zhifubaoPayService.createOrder_vip_xcx(user, code, vipId, adAccountId);
            map.put(ResponseCode.RET, ResponseCode.SUCC);
            map.put(ResponseCode.DATA, alipayTradeCreateResponse);
        } catch (BaseException e) {
            ResponseCode.printException(map, e, request);
        }

        OutputUtil.renderText(request, response, map);
    }

    /**
     * 创建app支付优惠券套餐订单
     *
     * @param token
     * @param mealId      套餐id
     * @param adAccountId 区域id
     * @param session
     * @param request
     * @param response
     */
    @RequestMapping("/createOrder_meal")
    @PreventDuplication(expireSeconds = 5)
    public void createOrder_meal(String token, Integer mealId, Integer adAccountId, HttpSession session, HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> map = new HashMap<String, Object>();
        try {

            User user = tokenService.getUser(token);
            Assert.notNull(mealId, "-180001", "主键id不能为空");
            Assert.notNull(adAccountId, "-10001", "区域id不能为空");
            String result = zhifubaoPayService.createOrder_meal(user, mealId, adAccountId);

            map.put(ResponseCode.RET, ResponseCode.SUCC);
            map.put(ResponseCode.DATA, result);
        } catch (BaseException e) {
            ResponseCode.printException(map, e, request);
        }

        OutputUtil.renderText(request, response, map);
    }

    /**
     * 支付宝小程序创建优惠券套餐订单
     *
     * @param token
     * @param code        微信授权码
     * @param mealId      套餐id
     * @param adAccountId 区域id
     * @param session
     * @param request
     * @param response
     */
    @RequestMapping("/createOrder_meal_xcx")
    @PreventDuplication(expireSeconds = 5)
    public void createOrder_meal_xcx(String token, String
            code, Integer mealId, Integer adAccountId, HttpSession session, HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> map = new HashMap<String, Object>();
        try {

            User user = tokenService.getUser(token);
            Assert.notNull(mealId, "-180001", "主键id不能为空");
            Assert.notNull(adAccountId, "-10001", "区域id不能为空");

            AlipayTradeCreateResponse alipayTradeCreateResponse = zhifubaoPayService.createOrder_meal_xcx(user, code, mealId, adAccountId);

            map.put(ResponseCode.RET, ResponseCode.SUCC);
            map.put(ResponseCode.DATA, alipayTradeCreateResponse);
        } catch (BaseException e) {
            ResponseCode.printException(map, e, request);
        }

        OutputUtil.renderText(request, response, map);
    }

    /**
     * 支付宝信用免押
     *
     * @param token
     * @param adAccountId
     * @param money
     * @param remark
     * @param rechargeType
     * @param session
     * @param request
     * @param response
     */
    @RequestMapping("/fundAuthOrderAppFreeze")
    @PreventDuplication(expireSeconds = 5)
    public void fundAuthOrderAppFreeze(String token, Integer adAccountId, Double money, String remark,
                                       @RequestParam(defaultValue = "8") Integer rechargeType, HttpSession session, HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> map = new HashMap<String, Object>();
        try {

            User user = tokenService.getUser(token);

            String freeze = zhifubaoPayService.fundAuthOrderAppFreeze(user.getAccountId(), user.getUserId(), money, remark, adAccountId, rechargeType);

            map.put(ResponseCode.RET, ResponseCode.SUCC);
            map.put(ResponseCode.DATA, freeze);
        } catch (BaseException e) {
            ResponseCode.printException(map, e, request);
        }

        OutputUtil.renderText(request, response, map);
    }

    /**
     * 信用押金解冻
     *
     * @param token
     * @param request
     * @param response
     */
    @RequestMapping("/unfreeze")
    @PreventDuplication(expireSeconds = 5)
    public void zfbFundAuthOrderAppUnfreeze(String token, HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> map = new HashMap<String, Object>();
        try {

            User user = tokenService.getUser(token);
            if (user == null) {
                throw new BaseException("-1001", "登录已过期，请重新登录");
            }
            Boolean freeze = zhifubaoPayService.zfbFundAuthOrderAppUnfreeze(user);

            map.put(ResponseCode.RET, ResponseCode.SUCC);
            map.put(ResponseCode.DATA, freeze);
        } catch (BaseException e) {
            ResponseCode.printException(map, e, request);
        }

        OutputUtil.renderText(request, response, map);
    }

}
